﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Mimoza.GUI
{
    public partial class BaseWizard : Form, IWizard
    {
        private enum PageStyle { SelectedPage, EnabledPage, ActivePage, DisabledPage };
        private WizardMode m_mode;
        private IWizardPage m_currentPage;
        private object m_userData;

        public BaseWizard()
        {
            InitializeComponent();
        }

        private void CloneStyles(PageStyle style, System.Windows.Forms.Panel dstPage, int pageNumber)
        {
            System.Windows.Forms.Panel srcPage;
            System.Windows.Forms.Label srcPageLabel;
            System.Windows.Forms.Label dstPageLabel;

            if (style == PageStyle.SelectedPage && this.m_mode == WizardMode.Wizard) srcPage = this.wSelectedPage;
            else if (style == PageStyle.EnabledPage && this.m_mode == WizardMode.Wizard) srcPage = this.wEnabledPage;
            else if (style == PageStyle.SelectedPage && this.m_mode == WizardMode.PropertySheet) srcPage = this.psSelectedPage;
            else if (style == PageStyle.EnabledPage && this.m_mode == WizardMode.PropertySheet) srcPage = this.psEnabledPage;
            else if (style == PageStyle.ActivePage && this.m_mode == WizardMode.PropertySheet) srcPage = this.psActivePage;
            else srcPage = this.disabledPage;

            srcPageLabel = srcPage.Controls[0] as System.Windows.Forms.Label;
            dstPageLabel = dstPage.Controls[0] as System.Windows.Forms.Label;

            // 
            // clone panel
            // 
            dstPage.BackColor = srcPage.BackColor;
            dstPage.Size = srcPage.Size;

            if (pageNumber >= 0)
            {
                dstPage.Location = new Point(srcPage.Location.X, srcPage.Size.Height * (pageNumber - 1));
            }
            // 
            // clone label
            // 
            dstPageLabel.Enabled = srcPageLabel.Enabled;
#warning  !!!----Help me to fix very strange behavor----!!!
#if !WindowsCE
            dstPageLabel.Font =  new Font(srcPageLabel.Font.Name,10,srcPageLabel.Font.Style);
#endif
            dstPageLabel.ForeColor = srcPageLabel.ForeColor;
            dstPageLabel.Location = srcPageLabel.Location;
            dstPageLabel.Size = srcPageLabel.Size;

#if !WindowsCE  
            if ( this.m_mode == WizardMode.PropertySheet )
            {
                System.Windows.Forms.LinkLabel label = dstPageLabel as System.Windows.Forms.LinkLabel;
                label.LinkColor = srcPageLabel.ForeColor;
                label.ActiveLinkColor = srcPageLabel.ForeColor;
                label.DisabledLinkColor = srcPageLabel.ForeColor;
                label.VisitedLinkColor = srcPageLabel.ForeColor;           
            }
#endif
        }

        private void UpdateWizardState()
        {
            int pageNum = 0;
            bool sprev = true;
            bool snext = false;
            bool sok = true;

            this.SuspendLayout();
            foreach (System.Windows.Forms.Panel panel in this.pagesPanel.Controls)
            {
                IWizardPage page = panel.Tag as IWizardPage;
                UserControl cpage = panel.Tag as UserControl;
                if (null != page)
                {
                    pageNum++;
                    snext = true;

                    if (!page.IsConfigured)
                    {
                        sok = false;
                    }

                    if (this.m_currentPage == page)
                    {
                        title.Text = page.PageTitle;
                        CloneStyles(PageStyle.SelectedPage, panel, pageNum);

                        if (pageNum == 1) sprev = false;
                        snext = false;

                        cpage.Dock = DockStyle.Fill;
                        cpage.Location = new Point(0, 0);

                        this.mainPanel.Controls.Clear();
                        this.mainPanel.Controls.Add(cpage);

                        cpage.Focus();
                    }
                    else
                    {
                        if (cpage.Enabled)
                        {
                            CloneStyles(PageStyle.EnabledPage, panel, pageNum);
                        }
                        else
                        {
                            CloneStyles(PageStyle.DisabledPage, panel, pageNum);
                        }
                    }
                }
            }

            this.Prev.Enabled = sprev;
            this.Next.Enabled = snext;
            if (m_mode == WizardMode.Wizard)
            {
                this.OK.Enabled = sok;
            }
#if !WindowsCE
            if (!sok) this.AcceptButton = this.Next;
            else this.AcceptButton = this.OK;
#endif
            this.ResumeLayout(false);
        }

        private int GetNumberOfPages()
        {
            int pageNum = 0;

            foreach (System.Windows.Forms.Panel panel in this.pagesPanel.Controls)
            {
                IWizardPage page = panel.Tag as IWizardPage;
                if (null != page)
                {
                    pageNum++;
                }
            }

            return pageNum;
        }

        private void Next_Click(object sender, EventArgs e)
        {
            this.NextPage();
        }
        private void Prev_Click(object sender, EventArgs e)
        {
            this.PrevPage();
        }

        private void OK_Click(object sender, EventArgs e)
        {
            if (!this.m_currentPage.Try2LeavePage(WizardPageLeavingDirection.Change))
            {
                this.DialogResult = DialogResult.None;
            }
            else
            {
                this.OnFinish();
            }
        }

        private void selectPage_Click(object sender, EventArgs e)
        {
            if (this.m_mode == WizardMode.Wizard) return;

            if (this.m_currentPage.Try2LeavePage(WizardPageLeavingDirection.Change))
            {
                if (sender is System.Windows.Forms.Panel)
                {
                    this.m_currentPage = (sender as System.Windows.Forms.Panel).Tag as IWizardPage;
                }
                else if (sender is System.Windows.Forms.LinkLabel)
                {
                    this.m_currentPage = (sender as System.Windows.Forms.LinkLabel).Tag as IWizardPage;
                }

                this.UpdateWizardState();
            }
        }

        private void BaseWizard_Shown(object sender, EventArgs e)
        {
            if (null != this.m_currentPage)
            {
                (this.m_currentPage as UserControl).Focus();
            }
        } 

        #region IWizard Members
        public virtual void Init(WizardMode mode)
        {
            this.m_mode = mode;

            if (m_mode != WizardMode.Wizard)
            {
                this.Next.Visible = false;
                this.Prev.Visible = false;
                this.OK.Text = "OK";
            }

            if (m_mode == WizardMode.Dialog)
            {
                this.pagesPanel.Visible = false;
                this.titlePanel.Visible = false;
            }

            this.Next.Click += new EventHandler(Next_Click);
            this.Prev.Click += new EventHandler(Prev_Click);
            this.OK.Click += new EventHandler(OK_Click);
        }

        public WizardMode Mode 
        {
            get 
            {
                return m_mode;
            }
        }

        public object UserData
        {
            get
            {
                return m_userData;
            }
            set
            {
                m_userData = value;
            }
        }

        public IWizardPage CurrentPage
        {
            get
            {
                return this.m_currentPage;
            }
            set
            {
                this.m_currentPage = value;

                UpdateWizardState();
                (this.m_currentPage as UserControl).Focus();
            }
        }

        public DialogResult Start()
        {
            foreach (Control cont in this.pagesPanel.Controls)
            {
                if (cont.Enabled && cont.Tag is IWizardPage)
                {
                    this.m_currentPage = cont.Tag as IWizardPage;
                    if (null != this.m_currentPage)
                    {
                        this.m_currentPage.EnterPage();
                    }
                    UpdateWizardState();
                    break;
                }
            }

            if (this.m_mode != WizardMode.Wizard)
            {
                this.OK.Enabled = false;
            }
            return this.ShowDialog();
        }
        public void NextPage()
        {
            bool ready = false;

            if (!this.m_currentPage.Try2LeavePage(WizardPageLeavingDirection.Forward)) return;

            foreach (Control cont in this.pagesPanel.Controls)
            {
                if (cont.Enabled && cont.Tag is IWizardPage)
                {
                    if (ready)
                    {
                        IWizardPage page = cont.Tag as IWizardPage;

                        page.EnterPage();
                        this.m_currentPage = page;

                        UpdateWizardState();
                        break;
                    }

                    if (this.m_currentPage == cont.Tag as IWizardPage)
                    {
                        ready = true;
                    }
                }
            }
            (this.m_currentPage as UserControl).Focus();
            this.OnNextPage();
        }
        public void PrevPage()
        {
            bool ready = false;

            if (!this.m_currentPage.Try2LeavePage(WizardPageLeavingDirection.Back)) return;
            for (int i = this.pagesPanel.Controls.Count - 1; i >= 0; i--)
            {
                Control cont = this.pagesPanel.Controls[i];
                if (cont.Enabled && cont.Tag is IWizardPage)
                {
                    if (ready)
                    {
                        this.m_currentPage = cont.Tag as IWizardPage;
                        UpdateWizardState();
                        break;
                    }

                    if (this.m_currentPage == cont.Tag as IWizardPage)
                    {
                        ready = true;
                    }
                }
            }
            (this.m_currentPage as UserControl).Focus();
            this.OnPrevPage();
        }
        public void AddPage(IWizardPage page)
        {
            int pageNum = this.GetNumberOfPages();
            System.Windows.Forms.Panel dstPage = new System.Windows.Forms.Panel();
            System.Windows.Forms.Label dstPageLabel;

            if (this.m_mode == WizardMode.Wizard)
            {
                dstPageLabel = new System.Windows.Forms.Label();
            }
            else
            {
                dstPageLabel = new System.Windows.Forms.LinkLabel();
                (dstPageLabel as System.Windows.Forms.LinkLabel).Click += new EventHandler(selectPage_Click);
            }

            page.Init(this);

            dstPageLabel.Text = page.PageName;
            dstPageLabel.Tag = page;

            dstPage.Controls.Add(dstPageLabel);
            dstPage.Tag = page;
            dstPage.Enabled = (page as UserControl).Enabled;
            dstPage.Visible = (page as UserControl).Visible;
            dstPage.TabStop = false;

            if (m_mode == WizardMode.Dialog)
            {
                (page as UserControl).BorderStyle = BorderStyle.FixedSingle;
            }
            
            if (dstPage.Enabled)
            {
                CloneStyles(PageStyle.EnabledPage, dstPage, pageNum);
            }
            else
            {
                CloneStyles(PageStyle.DisabledPage, dstPage, pageNum);
            }

            this.pagesPanel.Controls.Add(dstPage);
            page.OnPageModified += new PageEvent(page_OnPageModified);
            UpdateWizardState();
        }

        void page_OnPageModified(object page1)
        {
            bool sok = true;

            foreach (System.Windows.Forms.Panel panel in this.pagesPanel.Controls)
            {
                IWizardPage page = panel.Tag as IWizardPage;
                if (null != page)
                {
                    if (!page.IsConfigured)
                    {
                        sok = false;
                    }
                }
            }
            this.OK.Enabled = sok;
        }

        public void DeletePagesFrom(int pageIndexFrom)
        {
            List<Control> toDelete = new List<Control>();

            int i = 0;
            foreach (System.Windows.Forms.Panel panel in this.pagesPanel.Controls)
            {
                IWizardPage page = panel.Tag as IWizardPage;
                if (null != page)
                {
                    i++;
                    if (i == pageIndexFrom)
                    {
                        this.m_currentPage = page;
                    }
                    else if (i > pageIndexFrom)
                    {
                        toDelete.Add(panel);
                    }
                }
            }

            foreach (Control cont in toDelete)
            {
                this.pagesPanel.Controls.Remove(cont);
            }

            UpdateWizardState();
            (this.m_currentPage as UserControl).Focus();
        }

        public virtual void OnPrevPage() { }
        public virtual void OnNextPage() { }
        public virtual void OnFinish() { }
        public virtual void OnCancel() { }

        #endregion

    }
}